/* 文件格式转换、文件上传、文件导出等数据处理方法 */

import { message } from "ant-design-vue";

/**
 * 下载二进制流文件转 指定格式
 * @param data Blob对象
 * @param fileName 文件名
 *  @param fileType 文件类型 不传默认zip
 */
export const DownloadBlobToAssignFile = (data: any, fileName: string): void => {
  const blob = new Blob([data], { type: "application/octet-stream" });
  const ele = document.createElement("a");
  // 创建下载的链接
  const href = window.URL.createObjectURL(blob);
  ele.style.display = "none";
  ele.href = href;
  // 下载后文件名
  ele.download = fileName;
  document.body.appendChild(ele);
  // 点击下载
  ele.click();
  // 下载完成移除元素
  document.body.removeChild(ele);
  // 释放掉blob对象
  window.URL.revokeObjectURL(href);
  message.success(`下载成功：${fileName}`);
};

/**
 * 下载二进制流文件转 xlsx
 * @param data Blob对象
 * @param fileName 文件名
 */
export const DownloadBlobToXlsx = (data: any, fileName: string): void => {
  const blob = new Blob([data], {
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  });
  const ele = document.createElement("a");
  // 创建下载的链接
  const href = window.URL.createObjectURL(blob);
  ele.style.display = "none";
  ele.href = href;
  // 下载后文件名
  ele.download = fileName;
  document.body.appendChild(ele);
  // 点击下载
  ele.click();
  // 下载完成移除元素
  document.body.removeChild(ele);
  // 释放掉blob对象
  window.URL.revokeObjectURL(href);
  message.success(`下载成功：${fileName}.${href.split(".").at(-1)}`);
};
/**
 * 根据环境变量获取图片真实地址
 * @param url
 * @returns
 */
export const getRealImgUrl = (url = ""): string => {
  const baseUrl = import.meta.env.VITE_BASE_URL;
  const newUrl = encodeURI(url).replace(/%5B/g, "[").replace(/%5D/g, "]");
  return `${baseUrl}/static/${newUrl}`;
};

type _g6TsTableDeleteParams = {
  current: number; // 列表当前的页码
  pageSize: number; // 列表当前的每页条数
  total: number; // 列表数据的总条数
  tableLength: number; // 当前列表的数据有多少条
  delKeysLength: number; // 要删除的数据有多少条
};

/**
 * Table列表的数据在删除时进行的检查
 * -
 * 删除后重新获取列表数据之前先判断当前是否处于最后一页
 * -
 * 如果符合情况则向前倒退一页再进行数据的请求
 * -
 * @param paramObj 类型: _g6TsTableDeleteParams, 包含: current、pageSize、total、tableLength、delKeysLength
 * -
 * @返回 检查后的最新当前页 类型: number
 */
export const tableDeleteCheck = (paramObj: _g6TsTableDeleteParams): any => {
  const { current, pageSize, total, tableLength, delKeysLength } = paramObj;
  let newCurrent = current; // 当前pageSize条件下一共有多少个分页的按钮数量
  const paginationBtnNums = Math.ceil(total / pageSize); // 当前有大于一个的分页按钮, 并且当前页在最后一页
  if (current > 1 && current === paginationBtnNums) {
    if (tableLength === delKeysLength) {
      newCurrent = current - 1;
    }
  }

  return newCurrent;
};
/**
 * 获取文件名（方式2）
 * @param fileName
 * @returns
 */
export const getFileName2 = (fileName = ""): string => {
  return fileName.substring(0, fileName.lastIndexOf("."));
};

/**
 * 人脸库获取上传人脸照片的文件名
 * @param fileName
 * @returns
 */
export const getFileName = (fileName = ""): string => {
  if (!fileName) {
    return "";
  }
  const index = fileName.lastIndexOf(".");
  const name = fileName.substring(0, index);
  const lastIndex = name.lastIndexOf("/");
  return name.substring(lastIndex + 1);
};

/**
 * 获取文件名后缀
 * @param fileName
 * @returns
 */
export const getFileSuffix = (fileName = ""): string => {
  if (!fileName) {
    return "";
  }
  const index = fileName.lastIndexOf(".");
  return fileName.substring(index + 1);
};

/**
 * 将数组字符串转为以逗号分割的字符串
 * @param arr 需要被分割为字符串的数组
 */
export const arr2Str = (
  arr: number[] | string[] | undefined[]
): string | undefined => {
  // console.log('$F_Arr2Str:', arr);
  if (arr !== undefined) {
    if (arr.length !== 0) {
      return arr.join(",");
    }
  }
};

/**
 *  模拟递归查找数据
 * @param keys  需要查找的值
 * @param datas  查找数据
 * @param newList  不用传 结果
 * @returns  newList
 */
export const findTreeData = (
  keys: string[],
  datas: any[],
  newList: any[] = []
): Array<any> => {
  const stack = [...datas]; // 使用栈来模拟递归调用
  while (stack.length > 0) {
    const item = stack.pop();

    if (keys.includes(item.id)) {
      newList.push(item);
    } else {
      if (item.children && item.children.length > 0) {
        stack.push(...item.children); // 将子节点加入栈中继续遍历
      }
    }
  }
  return newList.reverse();
};

/**
 * 保留n位小数并格式化输出（不足的部分补0）
 * @param value
 * @param n
 * @returns
 */
export const fomatFloat = (value: number, n: number): number => {
  const f = Math.round(value * Math.pow(10, n)) / Math.pow(10, n);
  let s = f.toString();
  const rs = s.indexOf(".");
  if (rs < 0) {
    s += ".";
  }
  for (let i = s.length - s.indexOf("."); i <= n; i++) {
    s += "0";
  }
  return Number(s);
};

/**
 * 将对象的所有属性值转换为字符串最后拼接成一个字符串
 * @param obj
 * @returns
 */
export const obj2str = (obj: any): string => {
  let str = "";
  for (const key in obj) {
    if (typeof obj[key] === "object") {
      if (obj[key] === null) {
        str += "";
      } else {
        str += obj2str(obj[key]);
      }
    } else {
      str += obj[key];
    }
  }
  return str;
};

/**
 * 超出权限
 * @param obj  SOKET 消息体
 */

export const exceedAuthority = (obj: any): void => {
  if (obj.message === "EXPORT_PREPARE_RESULT") {
    obj.data.includes("成功")
      ? message.success(obj.data)
      : message.error(obj.data);
  }
  if (
    obj.message === "PERSON_DATA_UPDATE_MESSAGE" ||
    obj.message === "ROLE_UPDATE"
  ) {
    message.warning(
      obj.message === "PERSON_DATA_UPDATE_MESSAGE"
        ? "当前账号数据权限发生变更，需要进行重新登录"
        : "当前账号角色权限发生变更，需要进行重新登录"
    );
    let timer: NodeJS.Timeout;
    timer = setTimeout(() => {
      window.sessionStorage.clear();
      window.location.replace("/login");
      clearTimeout(timer);
    }, 1500);

    return;
  }
};

/**
 * 根据路径和id拼图片完整路径
 * @param url
 * @param id
 * @returns
 */
export const getImgUrl = (url = ""): string => {
  return `${url}?t=${new Date().getTime()}`;
};

/**
 *  对象深比较 不管对象内部数据索引顺序
 * @param obj1  对比对象1
 * @param obj2 对比对象2
 * @returns true|false true是一致的 false不一致
 */
export const deepEqual = (
  obj1: any,
  obj2: any,
  ignoreFields: string[] = []
): boolean => {
  // 检查基本类型的相等性
  if (obj1 === obj2) {
    return true;
  }

  // 检查 null 或者 undefined
  if (obj1 === null || obj2 === null) {
    return false;
  }

  // 获取 obj1 和 obj2 的类型
  const type1 = Object.prototype.toString.call(obj1);
  const type2 = Object.prototype.toString.call(obj2);

  // 检查类型是否相同
  if (type1 !== type2) {
    return false;
  }

  // 根据类型进行比较
  switch (type1) {
    case "[object Object]":
      return deepEqualObjects(obj1, obj2, ignoreFields);
    case "[object Array]":
      return deepEqualArrays(obj1, obj2, ignoreFields);
    case "[object Date]":
      return obj1.getTime() === obj2.getTime();
    case "[object RegExp]":
      return obj1.toString() === obj2.toString();
    default:
      return false;
  }
};

const deepEqualObjects = (
  obj1: any,
  obj2: any,
  ignoreFields: string[]
): boolean => {
  const keys1 = Object.keys(obj1).filter((key) => !ignoreFields.includes(key));
  const keys2 = Object.keys(obj2).filter((key) => !ignoreFields.includes(key));

  if (keys1.length !== keys2.length) {
    return false;
  }

  for (const key of keys1) {
    if (
      !obj2.hasOwnProperty(key) ||
      !deepEqual(obj1[key], obj2[key], ignoreFields)
    ) {
      return false;
    }
  }

  return true;
};

const deepEqualArrays = (
  arr1: any,
  arr2: any,
  ignoreFields: string[]
): boolean => {
  if (arr1.length !== arr2.length) {
    return false;
  }

  const visited = new Array(arr2.length).fill(false);

  for (let i = 0; i < arr1.length; i++) {
    let found = false;

    for (let j = 0; j < arr2.length; j++) {
      if (!visited[j] && deepEqual(arr1[i], arr2[j], ignoreFields)) {
        visited[j] = true;
        found = true;
        break;
      }
    }

    if (!found) {
      return false;
    }
  }

  return true;
};

// 统计在线/全部个数
export const getOnlineCount = (tree: any, key: string, count = 0) => {
  if (tree !== null) {
    if (tree[0]?.type === 0) {
      const subCount = tree.reduce(
        (pre: number, cru: any) => pre + (!!cru[key] ? 0 : 1),
        0
      );
      count += subCount;
    }
    for (let i = 0; i < tree.length; i++) {
      const node = tree[i];
      if (node.children) {
        count = getOnlineCount(node.children, key, count) as number;
      }
    }
    return count;
  }
};

// 统计报警器在线/全部个数
export const getAvOnlineCount = (tree: any, key: string, count = 0) => {
  if (tree !== null) {
    if (tree[0]?.type === 2) {
      const subCount = tree.reduce(
        (pre: number, cru: any) => pre + (cru[key] === 0 ? 0 : 1),
        0
      );
      count += subCount;
    }
    for (let i = 0; i < tree.length; i++) {
      const node = tree[i];
      if (node.children) {
        count = getAvOnlineCount(node.children, key, count) as number;
      }
    }
    return count;
  }
};
